﻿using AJWPFAdmin.Core;
using AJWPFAdmin.Core.Enums;
using AJWPFAdmin.Core.GlobalEvents;
using AJWPFAdmin.Core.HardwareSDKS.EQLED;
using AJWPFAdmin.Core.HardwareSDKS.HIKVision;
using AJWPFAdmin.Core.HardwareSDKS.Models;
using AJWPFAdmin.Core.HardwareSDKS.VzClient;
using AJWPFAdmin.Core.Logger;
using AJWPFAdmin.Core.Models;
using AJWPFAdmin.Core.Models.EF.Tables;
using AJWPFAdmin.Core.Mvvm;
using AJWPFAdmin.Core.Utils;
using AJWPFAdmin.Modules.Main.Views;
using AJWPFAdmin.Services;
using AJWPFAdmin.Services.EF;
using DocumentFormat.OpenXml.Wordprocessing;
using Masuit.Tools;
using MaterialDesignThemes.Wpf;
using Microsoft.EntityFrameworkCore;
using Newtonsoft.Json.Linq;
using Prism.Commands;
using Prism.Events;
using Prism.Regions;
using Prism.Services.Dialogs;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Formats.Asn1;
using System.Linq;
using System.Net;
using System.Reflection.Metadata;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Media;
using static AJWPFAdmin.Core.ExceptionTool;
using static AJWPFAdmin.Modules.Main.ViewModels.CarIdentificationPanelViewModel;

namespace AJWPFAdmin.Modules.Main.ViewModels
{
    public partial class DeviceScreenViewModel : ViewModelBase
    {
        

        private Visibility _emptyInfoVisibility;
        public Visibility EmptyInfoVisibility
        {
            get { return _emptyInfoVisibility; }
            set { SetProperty(ref _emptyInfoVisibility, value); }
        }

        private List<DeviceInfo> _deviceSource;


        private ObservableCollection<DeviceInfo> _devices;
        public ObservableCollection<DeviceInfo> DeviceList
        {
            get { return _devices; }
            set { SetProperty(ref _devices, value); }
        }


        private DelegateCommand<Grid> _cameraContainerLoadCmd;
        public DelegateCommand<Grid> CameraContainerLoadCmd =>
            _cameraContainerLoadCmd ?? (_cameraContainerLoadCmd = new DelegateCommand<Grid>(ExecuteCameraContainerLoadCmd));

        void ExecuteCameraContainerLoadCmd(Grid parameter)
        {

            var worker = new BackgroundWorker
            {
                WorkerReportsProgress = true
            };

            var curIP = CommonUtil.GetLocalIPV4();

            _setupEvent.Publish(_setupProgressModel);

            worker.DoWork += (_, e) =>
            {
                worker.ReportProgress(0, "初始化设备...");

                var watchhouseList = db.Watchhouses.Include(p => p.Passageways)
                    .Where(p => p.IP == curIP).Select(p => new
                    {
                        p.Id,
                        p.Name,
                        p.Code,
                        Passageways = p.Passageways.OrderBy(q => q.Code).Select(q => new
                        {
                            q.Id,
                            q.Name,
                            q.Code,
                            q.Direction
                        })
                    }).OrderBy(p => p.Code).ToList();

                var dbLedCfg = db.SystemConfigDictionaries
                    .Where(p => p.Key == SystemConfigKey.LEDConfig)
                    .FirstOrDefault();

                var ledConfig = CommonUtil.TryGetJSONObject<LEDConfig>(dbLedCfg?.StringValue) ?? new LEDConfig();

                if (ledConfig.EntranceTextArray == null)
                {
                    ledConfig.Init();
                }

                if (dbLedCfg != null)
                {
                    var passageways = watchhouseList
                    .SelectMany(p => p.Passageways)
                    .Select(p => new Passageway
                    {
                        Id = p.Id,
                        Name = p.Name,
                        Code = p.Code,
                        Direction = p.Direction
                    }).ToList();

                    var passagewayIds = passageways.Select(p => p.Id).Distinct().ToArray();

                    ledConfig.EQLEDs ??= new List<Core.HardwareSDKS.EQLED.EQLEDControlConfigModel>();

                    EQLEDSDK.SaveINI(ledConfig.EQLEDs);
                    if (ledConfig.EQLEDs.Count > 0)
                    {
                        EQLEDSDK.User_ReloadIniFile(EQLEDSDK.INIFile);
                        foreach (var eqled in ledConfig.EQLEDs)
                        {
                            try
                            {
                                EQLEDSDK.User_OpenScreen(eqled.CardAddress);

                                //var textArrayIndex = eqled.Direction == PassagewayDirection.进 ? 0 : 1;

                                //eqled.ProgramId = EQLEDSDK.User_AddProgram(eqled.CardAddress, false, 10);

                                //_logger.Debug($"EQLED:{eqled.CardAddress} ProgramId:{eqled.ProgramId}");

                                //var txt = eqled.CreateText("欢迎使用");

                                //var successFlag = EQLEDSDK.User_AddText(eqled.CardAddress, ref txt, eqled.ProgramId);

                                //var addSuccess = eqled.ProgramId != -1;

                                //if (addSuccess)
                                //{
                                //    needUpdateLEDCfg++;


                                //}
                                //var msg = !addSuccess ? "失败" : "成功";
                                //_logger.Debug($"EQLED:{eqled.CardAddress} 初始化{msg}");

                                foreach (var passageway in passageways)
                                {
                                    ledConfig.DisplayToLEDs(LEDTextScene.空闲,
                                        passageway,
                                        new Core.Models.EF.Tables.ShippingRecord
                                        {
                                            CreateDate = DateTime.Now,
                                        }, false);
                                }

                            }
                            catch (Exception exx)
                            {
                                _logger.Error($"EQLED:{eqled.CardAddress} 初始化失败", exx);
                            }

                        }

                    }
                }
                else
                {
                    _logger.Error("初始化EQLED设备失败:未配置任何EQLED数据");
                }

                var watchhouseIds = watchhouseList.Select(p => p.Id).ToList();

                var list = db.Devices.Where(p => watchhouseIds.Contains(p.WatchhouseId))
                    .AsNoTracking().OrderBy(p => p.Type).ToList();


                if (list.Any(p => p.Type == DeviceType.车牌识别相机_臻识))
                {
                    VzClientSDK.VzLPRClient_Setup();
                }

                if (list.Any(p => p.Type == DeviceType.监控相机_海康))
                {
                    CHCNetSDK.NET_DVR_Init();
                    CHCNetSDK.NET_DVR_SetConnectTime(3,3);
                    CHCNetSDK.NET_DVR_SetReconnect(10000, 1);
                }

                var matchedDeviceList = new List<DeviceInfo>();

                foreach (var wh in watchhouseList)
                {
                    foreach (var pw in wh.Passageways)
                    {
                        var devices = list
                        .Where(p => p.WatchhouseId == wh.Id && p.PassagewayId == pw.Id).OrderBy(p => p.Code).ToList();
                        if (devices.Count == 0)
                        {
                            continue;
                        }
                        foreach (var device in devices)
                        {
                            worker.ReportProgress(0, $"加载 {wh.Name}>{pw.Name}...");
                            var df = (DeviceInfo)device;
                            df.Direction = pw.Direction;
                            df.WatchhouseId = wh.Id;
                            df.WatchhouseCode = wh.Code;
                            df.WatchhouseName = wh.Name;
                            df.PassagewayId = pw.Id;
                            df.PassagewayCode = pw.Code;
                            df.PassagewayName = pw.Name;
                            if (df is VzCarIdentificationDevice vzDevice)
                            {
                                vzDevice.LEDTemplateTextArray
                                = df.Direction == PassagewayDirection.进
                                ? ledConfig.EntranceTextArray : ledConfig.EntranceTextArray;
                            }

                            matchedDeviceList.Add(df);

                        }
                    }
                }

                var count = matchedDeviceList.Count;

                for (int i = 0; i < count; i++)
                {
                    var item = matchedDeviceList.ElementAt(i);
                }

                e.Result = matchedDeviceList;

            };
            worker.ProgressChanged += (_, e) =>
            {
                _setupProgressModel.ProgressText = e.UserState?.ToString();
                _setupEvent.Publish(_setupProgressModel);
            };
            worker.RunWorkerCompleted += async (_, e) =>
            {
                if (e.Error != null)
                {
                    _setupProgressModel.ProgressText = $"设备加载失败:{e.Error.Message}";
                    _setupEvent.Publish(_setupProgressModel);
                    await Task.Delay(2000);

                    _setupProgressModel.Loading = false;
                    _setupEvent.Publish(_setupProgressModel);
                    return;
                }

                _setupProgressModel.Loading = false;

                _deviceSource = e.Result as List<DeviceInfo>;
                _setupProgressModel.Devices = _deviceSource;

                _setupEvent.Publish(_setupProgressModel);

                DeviceList.AddRange(_deviceSource);

                EmptyInfoVisibility = DeviceList.Count == 0 ? Visibility.Visible : Visibility.Collapsed;

                if (DeviceList.Count > 0)
                {
                    var div = Convert.ToInt32(DeviceList.Count <= 4 ? 2d : Math.Ceiling(DeviceList.Count / 2d));
                    var width = Math.Floor((parameter.ActualWidth - 64) / (double)div);
                    var height = Math.Floor((2d / 3d) * width) - 16;

                    var gridHeight = new GridLength(height, GridUnitType.Pixel);

                    parameter.RowDefinitions.AddRange(
                        new RowDefinition
                        {
                            Height = gridHeight,
                        },
                        new RowDefinition
                        {
                            Height = gridHeight,
                        }
                    );

                    for (int i = 0; i < div; i++)
                    {
                        parameter.ColumnDefinitions.AddRange(new ColumnDefinition
                        {
                            //Width = new GridLength(width, GridUnitType.Pixel),
                        });
                    }

                    var r = 0;
                    var c = 0;
                    for (int i = 0; i < DeviceList.Count; i++)
                    {
                        var ui = CreateCommonDeviceUI(DeviceList[i]);
                        Grid.SetRow(ui, r);
                        Grid.SetColumn(ui, c);
                        parameter.Children.Add(ui);

                        if ((i + 1) % div == 0)
                        {
                            c = 0;
                            r++;
                            continue;
                        }

                        c++;
                    }
                }
            };

            worker.RunWorkerAsync();
        }

        private UIElement CreateCommonDeviceUI(DeviceInfo dev)
        {
            var brush = (SolidColorBrush)new BrushConverter().ConvertFrom("#80000000");

            var card = new Card
            {
                Margin = new Thickness(4),
                DataContext = dev,
                BorderThickness = new Thickness(1),
                BorderBrush = brush
            };

            //ElevationAssist.SetElevation(card, Elevation.Dp4);

            card.MouseEnter += (sender, e) =>
            {
                (((Card)sender).DataContext as DeviceInfo).OnMouseEnterCmd.Execute();
            };
            card.MouseLeave += (sender, e) =>
            {
                (((Card)sender).DataContext as DeviceInfo).OnMouseLeaveCmd.Execute();
            };
            
            var drawerHost = new DrawerHost
            {
                TopDrawerBackground = brush,
                BottomDrawerBackground = brush
            };

            drawerHost.SetBinding(DrawerHost.IsBottomDrawerOpenProperty, new Binding(nameof(DeviceInfo.MouseHover))
            {
                Mode = BindingMode.TwoWay,
                UpdateSourceTrigger = UpdateSourceTrigger.PropertyChanged,
            });
            drawerHost.SetBinding(DrawerHost.IsTopDrawerOpenProperty, new Binding(nameof(DeviceInfo.MouseHover))
            {
                Mode = BindingMode.TwoWay,
                UpdateSourceTrigger = UpdateSourceTrigger.PropertyChanged,
            });

            var topDrawerContent = new StackPanel
            {
                Margin = new Thickness(8),
                Orientation = Orientation.Horizontal,
            };
            var textBlockForeground
                = Application.Current.FindResource("PrimaryHueLightForegroundBrush") as SolidColorBrush;
            var watchhouseTextblock = new TextBlock
            {
                FontSize = 16,
                Foreground = textBlockForeground,
            };
            watchhouseTextblock.SetBinding(TextBlock.TextProperty, new Binding(nameof(DeviceInfo.WatchhouseName)));
            topDrawerContent.Children.Add(watchhouseTextblock);

            topDrawerContent.Children.Add(new TextBlock
            {
                Margin = new Thickness(4, 0, 4, 0),
                FontSize = 16,
                Foreground = textBlockForeground,
                Text = ">"
            });

            var passagewayTextblock = new TextBlock
            {
                FontSize = 16,
                Foreground = textBlockForeground,
            };
            passagewayTextblock.SetBinding(TextBlock.TextProperty, new Binding(nameof(DeviceInfo.PassagewayName)));
            topDrawerContent.Children.Add(passagewayTextblock);

            topDrawerContent.Children.Add(new TextBlock
            {
                Margin = new Thickness(4, 0, 4, 0),
                FontSize = 16,
                Foreground = textBlockForeground,
                Text = ">"
            });

            var codeTextblock = new TextBlock
            {
                FontSize = 16,
                Foreground = textBlockForeground,
            };
            codeTextblock.SetBinding(TextBlock.TextProperty, new Binding(nameof(DeviceInfo.Code)));
            topDrawerContent.Children.Add(codeTextblock);

            drawerHost.TopDrawerContent = topDrawerContent;

            var bottomDrawerContent = new Grid();

            bottomDrawerContent.ColumnDefinitions.AddRange(new ColumnDefinition(), new ColumnDefinition());
            bottomDrawerContent.RowDefinitions.Add(new RowDefinition());

            var bottomDrawerStackPanel = new StackPanel
            {
                Margin = new Thickness(8),
                HorizontalAlignment = HorizontalAlignment.Right,
                Orientation = Orientation.Horizontal,
            };

            var isVz = dev is VzCarIdentificationDevice;
            var isSio = dev is SioReaderDevice;

            if (isVz || isSio)
            {
                var openBtn = new Button { Content = "开闸" };
                openBtn.SetBinding(Button.CommandProperty, new Binding(nameof(VzCarIdentificationDevice.ToggleSwitchCmd)));
                openBtn.CommandParameter = true;
                bottomDrawerStackPanel.Children.Add(openBtn);

                var closeBtn = new Button
                {
                    Margin = new Thickness(16, 0, 16, 0),
                    Content = "关闸"
                };
                closeBtn.SetBinding(Button.CommandProperty, new Binding(nameof(VzCarIdentificationDevice.ToggleSwitchCmd)));
                closeBtn.CommandParameter = false;
                bottomDrawerStackPanel.Children.Add(closeBtn);

                if (isVz)
                {
                    var triggerBtn = new Button
                    {
                        Margin = new Thickness(16, 0, 16, 0),
                        Content = "触发识别"
                    };
                    triggerBtn.SetBinding(Button.CommandProperty, new Binding(nameof(VzCarIdentificationDevice.RaiseCarPlatResultCmd)));
                    bottomDrawerStackPanel.Children.Add(triggerBtn);
                }
            }

            var msgTxt = new TextBlock
            {
                VerticalAlignment = VerticalAlignment.Center,
                Margin = new Thickness(4, 0, 4, 0),
                Foreground = (SolidColorBrush)Application.Current.FindResource("AJWhite")
            };
            msgTxt.SetBinding(TextBlock.TextProperty, new Binding(nameof(DeviceInfo.Message)));
            bottomDrawerContent.Children.Add(msgTxt);
            bottomDrawerContent.Children.Add(bottomDrawerStackPanel);
            Grid.SetColumn(bottomDrawerStackPanel, 1);

            drawerHost.BottomDrawerContent = bottomDrawerContent;

            var imgBox = new Image
            {
                Stretch = Stretch.Fill
            };

            imgBox.Loaded += (s, e) =>
            {
                dev.DeviceControlLoadCmd.Execute(imgBox);
            };

            drawerHost.Content = imgBox;

            card.Content = drawerHost;

            return card;
        }

        private DeviceSetupProgressModel _setupProgressModel;

        private DbService db;
        private DeviceSetupProgressEvent _setupEvent;
        private IEventAggregator _eventAggregator;
        private AJLog4NetLogger _logger;
        private AJConfigService _agCfgSvc;


        public DeviceScreenViewModel(DbService dbIns,
            IEventAggregator eventAggregator,
            AJLog4NetLogger logger,
            AJConfigService cfgSvc)
        {
            db = dbIns;
            _agCfgSvc = cfgSvc;
            _logger = logger;
            DeviceList = new ObservableCollection<DeviceInfo>();
            _setupProgressModel = new DeviceSetupProgressModel
            {
                Loading = true,
            };
            DeviceInfo.EventAggregator = _eventAggregator = eventAggregator;
            DeviceInfo.Logger = _logger;
            DeviceInfo.DbServiceBridgeHandle = () => DbService.GetDbContext(_agCfgSvc);
            _setupEvent = eventAggregator.GetEvent<DeviceSetupProgressEvent>();
            eventAggregator.GetEvent<ApplicationExitEvent>().Subscribe(() =>
            {
                foreach (DeviceInfo deviceInfo in DeviceList)
                {
                    try
                    {
                        deviceInfo.Close();
                    }
                    catch (Exception)
                    {

                    }
                }

                if (DeviceList.Any(p => p.Type == DeviceType.车牌识别相机_臻识))
                {
                    VzClientSDK.VzLPRClient_Cleanup();
                }
                if (DeviceList.Any(p => p.Type == DeviceType.监控相机_海康))
                {
                    CHCNetSDK.NET_DVR_Cleanup();
                }
            });
        }
    }

    public class DeviceTemplateSelector : DataTemplateSelector
    {
        public DataTemplate CarIdentificationCamera { get; set; }
        public DataTemplate CCTVCamera { get; set; }
        public DataTemplate Reader { get; set; }
        public DataTemplate None { get; set; }

        public override DataTemplate SelectTemplate(object item, DependencyObject container)
        {
            if (item == null)
            {
                return null;
            }
            if (item is not DeviceInfo device)
            {
                return null;
            }

            switch (device.Type)
            {
                case DeviceType.车牌识别相机_臻识:
                    return CarIdentificationCamera;
                case DeviceType.监控相机_海康:
                    return CCTVCamera;
                case DeviceType.高频读头:
                    return Reader;
                default:
                    return None;
            }
        }
    }
}
